import serialConfig
import numpy as np
from PySide6.QtCore import QTimer
import sys
from PySide6.QtWidgets import QApplication,QVBoxLayout
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg,NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import threading
import time
from aquarel import load_theme
# from PySide6.QtCore import QFile,QTextStream
from scipy.signal import iirfilter,lfilter
# 设计陷波滤波器
def Implement_Notch_Filter(time, band, freq, order, filter_type, data):
    fs   = 1/time
    nyq  = fs/2.0
    low  = freq - band/2.0
    high = freq + band/2.0
    low  = low/nyq
    high = high/nyq
    b, a = iirfilter(order, [low, high],  btype='bandstop',
                     analog=False, ftype=filter_type)
    filtered_data = lfilter(b, a, data)
    return filtered_data
sample_rate = 8192
sample_points = 0.001
mode_map = {"voltage":"Voltage/V","current":"Current/uA","charge":"Charge/nC"}
class MplCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        super().__init__(fig)
        self.xdata = []
        self.ydata = []
        self._plot_ref = None
        self.timer = QTimer()
        self.timer.setInterval(20)
        self.counter = 0
        self.filter_enable = 0
        self.isOriginal = False
        self.mode = "voltage"
        self.ts = 0.001
        self.timer.timeout.connect(self.update_plot)

    def update_plot(self):
        if self._plot_ref is None:
            plot_refs = self.axes.plot(self.xdata, self.ydata)
            self._plot_ref = plot_refs[0]
        else:
            self._plot_ref.set_xdata(self.xdata)
            if self.filter_enable:
                tempydata =Implement_Notch_Filter(self.ts,6,50,2,'butter',self.ydata)
                self._plot_ref.set_ydata(tempydata)
            else:
                self._plot_ref.set_ydata(self.ydata)
            self.counter += 1
            if(self.counter >=20):
                self.counter = 0
                self.axes.relim()  # 重新计算坐标范围
                self.axes.autoscale_view()  # 自动缩放视图到新范围
                if self.isOriginal:
                    self.axes.set_ylabel(mode_map[self.mode])
        self.draw()


def update_origin_data(obj):
    while True:
        lenx  = len(myshow.parsed_data)
        obj.mode = myshow.mode
        obj.xdata = list(range(lenx))
        # obj.ydata= lfilter(b, a, obj.ydata)
        # with myshow.data_lock:
            # obj.ydata = myshow.parsed_data
        time.sleep(0.01)


def update_fft_data(origin, fft,sp):
    while True:
        origin.ts = sp.sample_rate/10000
        data = np.array(origin.ydata)
        fft_data = np.fft.fft(data)
        freq = np.fft.fftfreq(len(data), d=origin.ts)
        positive_freqs = freq[: len(freq) // 2]
        positive_fft = np.abs(fft_data[: len(fft_data) // 2])
        fft.xdata = positive_freqs
        fft.ydata = positive_fft
        time.sleep(0.05)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    with open("style.qss", "r", encoding="UTF-8") as f:
        _style = f.read()
        app.setStyleSheet(_style)
    myshow = serialConfig.PySide6_Serial()
    myshow.sprate = sample_rate
    myshow.parsed_data = [0]*sample_rate
    theme = load_theme("boxy_light")
    theme.apply()
    origin_data_plot = MplCanvas()
    toolbar_origin =NavigationToolbar(origin_data_plot)
    layout_origin = QVBoxLayout()
    layout_origin.addWidget(toolbar_origin)
    layout_origin.addWidget(origin_data_plot)
    # origin_data_plot.axes.set_ylim(-1.8,1.8)
    origin_data_plot.ydata = myshow.parsed_data
    origin_data_plot.xdata = list(range(sample_rate))
    origin_data_plot.axes.set_title("original data")
    origin_data_plot.filter_enable = 0
    origin_data_plot.isOriginal = True
    read_thread = threading.Thread(target=update_origin_data, args=(origin_data_plot,))
    read_thread.daemon = True
    read_thread.start()

    origin_data_plot.timer.start()
    origin_data_plot.setObjectName("origin_data_plot")
    myshow.gridLayout.addLayout(layout_origin, 0, 0)

    # fft_data = np.fft.fft(data)
    # positive_fft = np.abs(fft_data[: len(fft_data) // 2])

    fft_data_plot = MplCanvas()
    fft_data_plot.axes.set_title("frequency spectrum")
    toolbar_fft = NavigationToolbar(fft_data_plot)
    layout_fft = QVBoxLayout()
    layout_fft.addWidget(toolbar_fft)
    layout_fft.addWidget(fft_data_plot)
    fft_data_plot.setObjectName("fft_data_plot")
    # fft_data_plot.ydata = positive_fft
    fft_data_plot.timer.start()

    read_thread2 = threading.Thread(
        target=update_fft_data, args=(origin_data_plot, fft_data_plot,myshow)
    )
    read_thread2.daemon = True
    read_thread2.start()

    myshow.gridLayout.addLayout(layout_fft, 0,1)

    myshow.show()
    sys.exit(app.exec())
